微服务网关终结者?Spring Cloud推出新成员Spring Cloud Gateway
导语:Spring Cloud Gateway基于Spring Boot 2,该项目提供了一个构建在Spring 生态之上的 API 网关。Spring Cloud Gateway旨在提供一种简单而有效的途径来发送API。
当传统的服务(例如数据库、消息队列、搜索引擎)在Cloud Foundry生态系统中广泛的应用和交易,有两种你可能不知道的服务发现方式。卷(Volume)服务[1]允许你做一个持久挂载的系统到你的应用。路由服务[2]允许拦截到你应用的所有HTTP流量。
路由服务
路由服务可以被用于很多目的,例如日志、限流、认证,从而做到应用无感知。
首先,让我们了解一下路由服务的工作原理。当路由服务绑定到应用,路由器将拦截到应用的所有请求,添加一些HTTP头以及保证请求完整性的签名,并将请求路由到对应服务(或者修改URL,或者仅仅返回一个错误的响应)。路由服务能做的事情请查看路由服务文档。
简单日志服务
这一节,我们学习如何使用Spring Cloud团队推出的API网关Spring Cloud Gateway构建一个简单的路由服务。这是一个简单的服务,它仅仅在日志中记录请求的详细信息,然后将请求转发到目标地址(类似路由服务文档中的Spring Boot实例[3])。
创建项目
首先,创建一个新的Spring项目。你必须保证使用Spring Boot 2.x版本(当前最新版本2.0.0 RC1),并且包含Gateway和Reactive Web的依赖。在这个例子中,我根据自己的偏爱使用Gradle,当然你也可以使用Maven。
路由谓词
接下来,我们需要设置网关路由,用于处理请求。如路由服务文档在Headers部分提到的,这里有3个header用于标识一个路由服务请求:
X-CF-Forwarded-Url:请求的目标URL
X-CF-Proxy-Signatur:验证请求用的token
X-CF-Proxy-Metadata:解析和验证X-CF-Proxy-Signature的帮助信息
上面这个Spring Cloud Gateway路由服务围绕谓词构建。在这个例子中,有3个基于Predicate的简单Header。如果一个请求,这3个谓词全都匹配,那我们转发该请求到http://google.com:80(很明显真实的场景不能这么做,后面我们将使用filter更新目标地址)。我们使用./gradlew bootRun命令启动服务,并且使用http客户端验证服务是否正常工作。
如你所见,路由服务处理了这3个Header,并且如我们所期待的将请求转发到google了(google返回了301作为响应)。
日志Filter
接下来,我们构建一个简单的Filter,用于记录进来的请求的一些信息。
最后调用chain.filter(exchange),表明这个Filter已经处理完成,并且将请求传给Filter链中的下一个Filter进行处理,或者如果这是链中最后一个Filter,则对请求放行。接下来,我们需要确保当路由服务处理请求时会调用Filter。
如你所见,我们使用filters()方法增加了日志过滤器。f是GatewayFilterSpec[4]类的实例,包含了常用filters的简便方法,例如添加Header、转发,或者开启Hystrix[5]。
如果我们使用HTTP客户端再次测试,我们将看到我们日志中的详细信息:
转发到目标URL
最后,我们需要确保请求被转发到了目标URI,而不是google。我们能使用另外的Filter完成这个目的。
这个值从X-CF-Forwarded-Url中获取,并且存储在Spring Cloud Gateway的特殊属性中,用于发送最终的请求。如果产生了异常,网关将停止处理请求,并且返回一个500。注意,和其他类型的路由服务一样,这是用于拒绝请求的通用模式。如果你需要拒绝请求,你可以仅仅返回500状态码,同时停止处理请求。
现在,在路由中写一个新的Filter:
ROUTE_TO_URL_FILTER_ORDER是一个常量,表明RouteToRequestUrlFilter类型的Filter在运行。我们需要确保我们前面定义的Filter 在它之后运行,这样我们的GATEWAY_REQUEST_URL_ATTR就不会被覆盖。另外,你可能要注意,我们从f.add换成了f.filter。这是因为当前版本的Spring Cloud Gateway不允许通过add方法进行设置。
我们通过HTTP客户端再验证一次:
注意,我们通过X-CF-Forwarded-Url的Header属性使用reddit替换掉了google。
部署
到这里,路由服务就可以部署了。你应该构建应用(Gradle用户使用./gradlew build命令),参照路由服务文档中的教程[6]部署。
总结
Spring Cloud Gateway刚出来不是很久,但是对于那些想在Cloud Foundry应用前面做一层处理的Java开发者来说,是非常有用的选择。如果你想看简单路由服务的最终源代码,在这里[7]。另外,有必要看看Spring Gloud Gateway的文档,包含了很多当前教程没有提到的有用的谓词和Filter。
文中链接
[1] https://docs.cloudfoundry.org/devguide/services/using-vol-services.html
[2] https://docs.cloudfoundry.org/services/route-services.html
[3] https://github.com/nebhale/route-service-example
[4] https://github.com/spring-cloud/spring-cloud-gateway/blob/v2.0.0.M6/spring-cloud-gateway-core/src/main/java/org/springframework/cloud/gateway/route/builder/GatewayFilterSpec.java
[5] https://github.com/Netflix/Hystrix
[6] https://docs.cloudfoundry.org/services/route-services.html#tutorial
[7] https://github.com/Fitzoh/simple-gateway-route-service
本文作者Andrew Fitzgerald,由邓启明翻译,转载本文请注明出处,技术原创及架构实践文章,欢迎通过公众号菜单「联系我们」进行投稿。
相关阅读:
高可用架构
改变互联网的构建方式
长按二维码 关注「高可用架构」公众号